import os
from datetime import datetime, timedelta
from typing import List, Optional, Any
from bson.objectid import ObjectId

from common.utils import format_validation_error, ToExcelFile

from mg_app_framework import HttpBasicHandler, MesCode, FileStream, log_exception
from pydantic import ValidationError, validator

from service_log_viewer.servce_constant import PaginationNode, HeaderCollection
from service_log_viewer.service.service_log_process import filter_service_logs, filter_servie_log_header, \
    filter_target_servie_log, import_server_log_config, upload_server_log_config, filter_server_log_config


class ServerLogHeaderHandler(HttpBasicHandler):
    """
    日志查询: header
    """

    async def get_process(self, *args, **kwargs):
        try:
            func_result = await filter_servie_log_header()
            self.send_response_data(MesCode.success, {**func_result}, "OK")
        except Exception as e:
            log_exception(e)
            self.send_response_data(MesCode.fail, {}, "fail")


class ServerLogsFilterHandler(HttpBasicHandler):
    """
    日志查询返回
    """

    class CheckModel(PaginationNode):
        process_code: Optional[str]  # 工序编码
        device_code: Optional[str]  # 设备编码
        api_string: Optional[str]  # 调用接口
        api_response_code: Optional[str]  # 返回结果
        time_section: Optional[List]  # 调用时间

        @validator("time_section", pre=True, always=True)
        def check_time_section(cls, v):
            if not v:
                now_time = datetime.now()
                return [now_time - timedelta(days=7), now_time]
            return [datetime.strptime(v[0], "%Y-%m-%d %H:%M:%S"), datetime.strptime(v[1], "%Y-%m-%d %H:%M:%S")]

    async def post_process(self, *args, **kwargs):
        try:
            check_node = self.CheckModel(**self.data)
            process_code = check_node.process_code
            device_code = check_node.device_code
            api_string = check_node.api_string
            api_response_code = check_node.api_response_code
            time_section = check_node.time_section
            pagination_node = PaginationNode(
                page=check_node.page,
                size=check_node.size
            )
            func_result = await filter_service_logs(
                process_code=process_code,
                device_code=device_code,
                api_string=api_string,
                api_response_code=api_response_code,
                time_section=time_section,
                pagination_node=pagination_node

            )
            self.send_response_data(MesCode.success, {**func_result, "header": HeaderCollection.SERVER_LOG_HEAD}, "OK")
        except ValidationError as v_e:
            self.send_response_data(MesCode.fail, {}, format_validation_error(v_e.errors()))
        except Exception as e:
            log_exception(e)
            self.send_response_data(MesCode.fail, {}, "fail")


class ServerTargetLogFilterHandler(HttpBasicHandler):
    """
    日志查询返回
    """

    class CheckModel(PaginationNode):
        uid: Any

        @validator("uid", pre=True, always=True)
        def check_uid(cls, v):
            return ObjectId(v)

    async def post_process(self, *args, **kwargs):
        try:
            check_node = self.CheckModel(**self.data)
            uid = check_node.uid

            func_result = await filter_target_servie_log(uid=uid)
            self.send_response_data(MesCode.success, func_result, "OK")
        except ValidationError as v_e:
            self.send_response_data(MesCode.fail, {}, format_validation_error(v_e.errors()))
        except Exception as e:
            log_exception(e)
            self.send_response_data(MesCode.fail, {}, "fail")


class FilterServerLogConfigHandler(HttpBasicHandler):

    async def post_process(self, *args, **kwargs):
        try:
            func_result = await filter_server_log_config()
            self.send_response_data(MesCode.success, {
                "data": func_result,
                "header": HeaderCollection.SERVER_LOG_CONFIG_HEAD
            }, '接口调用名称枚举配置导入成功')
        except Exception as e:
            log_exception(e)
            self.send_response_data(MesCode.fail, {}, "接口调用名称枚举配置导入异常:{}".format(str(e)))


class ImportServerLogConfigHandler(HttpBasicHandler):

    async def post_process(self, *args, **kwargs):
        file_path = ''
        try:
            files = self.request.files
            file = files.get('file')[0]
            file_path = ToExcelFile(file.get('filename', "接口调用名称枚举配置")).xls_save_path()
            with open(file_path, 'wb') as f:
                f.write(file.get('body'))
            await import_server_log_config(file_path)
            self.send_response_data(MesCode.success, '', '接口调用名称枚举配置导入成功')
        except Exception as e:
            log_exception(e)
            self.send_response_data(MesCode.fail, '', "接口调用名称枚举配置导入异常:{}".format(str(e)))
        finally:
            if file_path and os.path.exists(file_path):
                os.remove(file_path)


class UploadServerLogConfigHandler(HttpBasicHandler):

    async def get_process(self, *args, **kwargs):
        await self.post_process(*args, **kwargs)

    async def post_process(self, *args, **kwargs):

        try:
            file_name = "接口调用名称枚举配置"
            excel_file = ToExcelFile(file_name)
            file_path = excel_file.xls_save_path()

            await upload_server_log_config(file_path)
            if os.path.exists(file_path):
                output_data = FileStream(file_path)
                self.send_response_file(filename=excel_file.file_name, data=output_data, buf_size=1024)
                os.remove(file_path)
        except Exception as e:
            log_exception(e)
            self.send_response_data(MesCode.fail, None, '后台内部错误，导出报表失败:{}'.format(str(e)))
